package com.jasonclawson.dropwizardry.guice.support; import io.dropwizard.Configuration; import io.dropwizard.setup.Environment; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import lombok.extern.slf4j.Slf4j; import com.google.inject.AbstractModule; import com.google.inject.name.Names; /** * * @param <T> */ @Slf4j public class DropwizardEnvironmentModule<T extends Configuration> extends AbstractModule { private final T configuration; private final Environment environment; private Class<? super T> configurationClass; public DropwizardEnvironmentModule(Class<T> configurationClass, T configuration, Environment environment) { this.configurationClass = configurationClass; this.configuration = configuration; this.environment = environment; } @Override protected void configure() { bind(Configuration.class).toInstance(configuration); if(configurationClass != Configuration.class) { bind(configurationClass).toInstance(configuration); } bind(Environment.class).toInstance(environment); initConfigurationBindings(); } @SuppressWarnings("unchecked") private void initConfigurationBindings() { try { BeanInfo beanInfo = Introspector.getBeanInfo(configurationClass); PropertyDescriptor[] props = beanInfo.getPropertyDescriptors(); Object current = configuration; for(PropertyDescriptor prop : props) { Method readMethod = prop.getReadMethod(); if(readMethod.getParameterTypes().length == 0) { try { Object value = readMethod.invoke(current); //TODO: add support for binding generic types too! if(value.getClass().getGenericInterfaces().length > 0) { log.warn("Binding of generic types is not supported yet. Will not bind {}", value.getClass()); continue; } bind((Class<Object>)value.getClass()) .annotatedWith(Names.named(prop.getName())) .toInstance(value); log.debug("Binding {} annotated with \"{}\"", value.getClass(), prop.getName()); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { log.error("Unable to bind '{}' due to readMethod invoke error",prop.getName(), e); } } } } catch (IntrospectionException e) { log.error("Unable to introspect bean info for {}. I will try to continue without binding configurations", configurationClass); } } }